//This servlet handles the main functionality of the nettrust toolbar.It first populates the ratings and the comments depending on the nym that the user is in.
//Author:Shreyas Kamath

import java.sql.*;
import java.util.Date;
import java.io.*;
import java.util.*;
import java.util.HashMap;
import javax.servlet.http.*;
import javax.servlet.ServletException;
import javax.servlet.ServletConfig;


public class NetTrustFinalServlet extends HttpServlet{

	// The hashmaps which store the fields from the database
	private static HashMap hmInternalRating		= new HashMap();
	public static HashMap hmExplicitRating		= new HashMap();
	public static HashMap hmVisits		= new HashMap();
	public static HashMap hmLastDate	= new HashMap();
	public static HashMap hmInitDate	= new HashMap();
	public static HashMap hmBuddyAvgPositive	= new HashMap();
	public static HashMap hmBuddyAvgNegative	= new HashMap();
	public static HashMap hmComments = new HashMap();
	public static HashMap hmCommentCount=new HashMap();
	public static HashMap hmBuddyCount= new HashMap();
	public static String  strNymID		= null; // store nym ID from nym name
	public static int	iNewURLCount	= 0; // count of newly visited sites
	public static Vector VectorOfNewURLs	=new Vector(20,5);
		
	//variables for broadcasters
	public static final int MAX_BROADCASTERS = 5;
	public static String REGEX = ":";
	
	//Hashmaps for storing the broadcaster info
	public static HashMap hmBroadCaster1 = new HashMap();
	public static HashMap hmBroadCaster2 = new HashMap();
	public static HashMap hmBroadCaster3 = new HashMap();
	public static HashMap hmBroadCaster4 = new HashMap();
	public static HashMap hmBroadCaster5 = new HashMap();
	private static int iNumBroadcasters = 0;
	public static Vector vector_Broadcastername =new Vector(20,5);
	
	
	//The following  Constants are used to calculate the ratings
	public static final int	JanFirst2006 = 1;//1136091600; // seconds from epoch
	public static final int	MAXRATING = 5;// seconds from epoch
	//public static final long	ONEYEARINms			= 35000; // one year in milliseconds
	//public static final long		ONEDAYINms		= 2400; // one day in milliseconds
	//public static final int		THREEHOURSINms		= 300; // for testing reasons - 10 seconds
	//public static final int		ONEWEEKINms			= 16800; //for testing reasons - 30 seconds
	public static final int	THREEHOURSINms = 10800000; // 3 hrs in milliseconds
	public static final int	ONEWEEKINms	= 604800000; //one week in milliseconds
	public static final long ONEYEARINms = 31557600000L; // one year in milliseconds
	public static final long ONEDAYINms	= 86400000L; // one day in milliseconds
	public static final int	ONEDAY = 1; // one day in days
	public static final int	ONEWEEK = 7; // one day in days
	public static final int	ONEYEAR = 365; // one day in days
	
	
	
	public void init(ServletConfig config) 
	{
		System.out.println("NetTrustFinalServlet: init()");
		loadNym("home");
	}
		
		
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// function loadNym()
	// Takes in a string - the nym as parameter
	// Is a wrapper for readRatingsFromDB()
	// Loads the necessary fields into the data structures
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

	public static int loadNym( String strNym )
	{
		readRatingsFromDB( strNym );
		GetBroadcasterRating("home", "ExpiryDate");
		return 1;
	}
	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// end of function loadNym
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	
	//This is the service method for the servlet which sends the xml response back to the main file. 
	public void doGet(HttpServletRequest request,HttpServletResponse response)    
		throws ServletException, IOException {

	String nym="home";
	String strCurrNym= request.getParameter("nym");
	if(!(nym.equals(strCurrNym)))
	{
		this.loadNym( strCurrNym );
		nym=strCurrNym;
	}
	// set the response type
	response.setContentType("text/xml; charset=UTF-8"); 
	response.setHeader("Cache-Control","no-cache");		
	//Parameter
	String strurl=null;
	// obtain the writer to write the response
	PrintWriter out = response.getWriter();
	out.println("<?xml version=\"1.0\"?>");  
	strurl = request.getParameter("url_val");
	//strurl="www.google.com";
	String strRating=this.returnRating(strurl);
	StringTokenizer rating=new StringTokenizer(strRating,",");
	String strfpositiverating=rating.nextToken();
	String strfnegativerating=null;
	if(rating.hasMoreTokens())
	{
		strfnegativerating=rating.nextToken();
		System.out.println("rating:"+strfnegativerating);
	}
	
	//Start printing the content of the xm file
	out.println("<values>");
	out.println("<positiverating id ='1'>");
	if(strfpositiverating !=null)
	{
		Float pos=Float.parseFloat(strfpositiverating);
		out.println(pos.intValue());
	}
	else 
	{
		//This value is used to flag that the positive rating does not exist for this url
		out.println("10");	
	}
	out.println("</positiverating>");
	out.println("<negativerating id ='2'>");
	if(strfnegativerating != null)
	{
		Float neg=Float.parseFloat(strfnegativerating);
		out.println(neg.intValue());
	}
	else
	{
		//This value is used to flag that the negative rating does not exist for this url
		out.println("-10");
	}	
	out.println("</negativerating>");
	
	//start printing the comments
	String strComments=this.returnComments(strurl);
	StringTokenizer stComments=new StringTokenizer(strComments,",");
	while(stComments.hasMoreTokens())
	{
		out.println("<Comment>");
		StringTokenizer stnameComment=new StringTokenizer(stComments.nextToken(),":");
		out.println("<SubmittedBy>");
		out.println(stnameComment.nextToken());
		out.println("</SubmittedBy>");
		out.println("<CommentValue>");
		out.println(stnameComment.nextToken());
		out.println("</CommentValue>");
		out.println("</Comment>");
	}
	String iNumComments=this.returnNumComments(strurl);
	String iNumBuddies=this.returnNumBuddies(strurl);
	out.println("<numberofcomments id='3'>");
	out.println(iNumComments);
	out.println("</numberofcomments>");
	out.println("<numberofbuddies id='4'>");
	out.println(iNumBuddies);
	out.println("</numberofbuddies>");
	//This protion sends the broadcaster rating.
	String strBroadcasterrating=ReturnBroadcasterRating(strurl);
	StringTokenizer stBroadcasterrating=new StringTokenizer(strBroadcasterrating,",");
	while(stBroadcasterrating.hasMoreTokens())
	{
		out.println("<Broadcaster>");
		String strBroadcaster=stBroadcasterrating.nextToken();
		StringTokenizer stBroadcaster=new StringTokenizer(strBroadcaster,":");
		out.println("<name>");
		out.println(stBroadcaster.nextToken());
		out.println("</name>");
		out.println("<rating>");
		out.println(stBroadcaster.nextToken());
		out.println("</rating>");
		out.println("</Broadcaster>");
	}	
	out.println("</values>");
	// close the writer
	out.close();	
	}
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// end of constructor
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	
	
	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// readRatingsFromDB()
	// Takes in a string - the nym of the user
	// Reads the entire database and fills up the hashmaps
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	public static void readRatingsFromDB( String strNym )
	{
		Connection	conn		= null;
		
		try
		{
			//Defines the Query statements
			Statement	getNymIDFromName;
			Statement	getBuddyRatings;
			Statement	getAllFieldsFromInternalRating;

			// the recordsets
			ResultSet	rsNymID;
			ResultSet	rsBuddy,rsBuddyCount;
			ResultSet	rsInternalRating;

			// establish a connection with the database
			conn = Connect();
			
			getNymIDFromName				= conn.createStatement();
			getBuddyRatings					= conn.createStatement();
			getAllFieldsFromInternalRating	= conn.createStatement();
			
			int			iCount = 0;
			try
			{
				// get the nym ID from nym name
				rsNymID = getNymIDFromName.executeQuery( "select nymid from nymnamemap where nymname='" + strNym + "'" );
				
				// get the nym ID for the nym name
				// strNymID is global
				while( rsNymID.next() )
				{
					strNymID = rsNymID.getString( "nymid" );
					//System.out.println( "Nym=" + nymid );
				}
				
				// get the details associated with Buddy Ratings
				rsBuddy = getBuddyRatings.executeQuery( "select urlName,ExplicitRating,CurrRating,Comments,internalrating.Nymid,NymName from nyminfo,internalrating,nymnamemap where nyminfo.BuddyId =internalrating.Nymid and nymnamemap.NymID=nyminfo.BuddyId and nyminfo.NymID='" + strNymID + "'" );
				//rsBuddyCount = getBuddyRatings.executeQuery( "select count(*) as BuddyCount from nyminfo where NymID='" + strNymID + "'");
				// get the fields in InternalRatings
				rsInternalRating = getAllFieldsFromInternalRating.executeQuery("select UrlName,ExplicitRating,CurrRating,NumVisits,LastDate,InitDate,Comments from internalrating where Nymid='" + strNymID + "'" );
				/*while( rsBuddyCount.next() )
				{
					// iCount=rsBuddyCount.getInt( "BuddyCount" );
				}
				*/
				// loop through all the records in Internal Ratings
				// and load them into the data structure
				while( rsInternalRating.next() )
				{
					// get the corresponding values
					String		strURLName	= rsInternalRating.getString( "urlName" );
					float			fExplicitRating	= rsInternalRating.getFloat( "ExplicitRating" );
					float			fInternalRating	= rsInternalRating.getFloat( "CurrRating" );
					int			iNumVisits		= rsInternalRating.getInt( "NumVisits" );
					long		lLastDate		= rsInternalRating.getLong( "LastDate" );
					long		lInitDate		= rsInternalRating.getLong( "InitDate" );
					//String 	strComments	  = rsInternalRating.getString("Comments");
					StringBuffer strbufComments=new StringBuffer();
					// convert from long/int to strings
					// as the hash map can store only strings
					String			strInitDate		= Long.toString( lInitDate );
					String			strLastDate		= Long.toString( lLastDate );
					String			strNumVisits	= Integer.toString( iNumVisits );
			
					String			strExplicitRating = Float.toString( fExplicitRating );
					String			strInternalRating = Float.toString( fInternalRating );
						
					// put data into the hashmaps
					hmInternalRating.put( strURLName, strInternalRating );
					hmExplicitRating.put( strURLName, strExplicitRating );
					hmVisits.put( strURLName, strNumVisits );
					hmLastDate.put( strURLName, strLastDate );
					hmInitDate.put( strURLName, strInitDate );
					
					
					
					// declare some variables for use inside the next while loop
					float			fBuddyRatingPositive = 0;
					float			fBuddyRatingNegative = 0;
					int			iCountPositive = 0;
					int			iCountNegative = 0;
					
					int 			iCommentCount=0;
					String strseperator1=",";
					String strseperator2=":";
					// loop through the buddy recordsets
					while( rsBuddy.next() )
					{             
						String strBuddyURL= rsBuddy.getString( "UrlName" );
					
						// if the url's match, add them
						// the ratings need to be separated into +ve and -ve
						// buddyID can be used to exclude some buddies explicitly in rating calculation
						if( strURLName.equals( strBuddyURL ) )
						{
							// int iBuddyID		= rsBuddy.getInt( "buddyid" );
							
							float fBuddyExplicitRating	=rsBuddy.getFloat( "ExplicitRating" );
							float fBuddyCurrRating 	=rsBuddy.getFloat("CurrRating");
							float fBuddyRating=0;
							if(fBuddyExplicitRating>0)
								fBuddyRating=fBuddyExplicitRating;
							else
								fBuddyRating=fBuddyCurrRating;
							String strComment=rsBuddy.getString("Comments");
							String strBuddyName=rsBuddy.getString("NymName");
							if(strComment != null)
							{
								strbufComments.append(strBuddyName);
								strbufComments.append(strseperator2);
								strbufComments.append(strComment);
								strbufComments.append(strseperator1);
								iCommentCount++;
							}								
							if ( fBuddyRating > 0 )
							{
								iCountPositive++;
								fBuddyRatingPositive += fBuddyRating;
							}
							else if ( fBuddyRating < 0 )
							{
								iCountNegative++;
								fBuddyRatingNegative += fBuddyRating;
							}
							iCount++;
						}
						
						
						
					}
					hmComments.put( strURLName, strbufComments.toString());
					hmBuddyCount.put(strURLName,Integer.toString(iCount));
					hmCommentCount.put(strURLName,Integer.toString(iCommentCount));
				
					float fAvgRatingPositive;
					float fAvgRatingNegative;
					
					if( iCountPositive != 0 )						
						fAvgRatingPositive = ( fBuddyRatingPositive ) / ( iCountPositive );
					else						
						fAvgRatingPositive = 0;

					if( iCountNegative != 0 )
						fAvgRatingNegative = ( fBuddyRatingNegative ) / ( iCountNegative );
					else
						fAvgRatingNegative = 0;
					
					// put it into the hash maps
					hmBuddyAvgPositive.put( strURLName, Float.toString( fAvgRatingPositive ) );
					hmBuddyAvgNegative.put( strURLName, Float.toString( fAvgRatingNegative) );
					
					rsBuddy.first();
			   }//end while loop
			}
			
			catch( Exception e )
			{
				System.out.print( "The following error occurred"+e );
				
			}//end catch
		}
		
		catch ( Exception e )
		{
			System.err.println ( "Cannot connect to database serverdue to" + e );
		}
		
		finally
		{
			if ( conn != null )
			{
				try
				{
					conn.close();
					System.out.println ( "Database connection terminated" );
				}				
				catch ( Exception e )
				{
					/* ignore close errors */ 
				}
			}
		}
	}
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// end of function readRatingsFromDB()
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// GetNymID()
	// Gets the 128 bit NymID corresponding to a nym using the nym name as the parameter
	// returns 128 bit NymID
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	public static String GetNymID(String strNym)
	{
		Connection conn =Connect();
		String strNymid=null;
		ResultSet rsNymID;
		try
		{
			Statement getNymID= conn.createStatement();
		      //Get the nymid corresponding to the nym name from the database 
			rsNymID=getNymID.executeQuery("select nymid from nymnamemap where nymname='" + strNym + "'");
			while( rsNymID.next() )
			{
				strNymid=rsNymID.getString("nymid");
			}
		}
		catch( Exception e )
		{
			System.out.println ( "Database Exception is " + e );
		};  
		return(strNymid);
	}	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// end of function GetNymID()
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// GetBroadcasterRating()
	// Gets the broadcasters rating corresponding to a nym using the nymname and the criteria identifies the criteria that is used to arrange the broadcasters.
	// populates the hashmaps with the broadcaster ratings
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	public static void GetBroadcasterRating(String strNym,String strCriteria)
	{
		String strNymID=GetNymID(strNym);
		String strBroadCasterName;
		String strUrl;
		String strRating;
		int iRating,ibroadcasterno;
		ResultSet rsBroadcasterInfo,rsBroadcasterName;
		Connection conn=Connect();
		try
		{
			Statement getBroadCasterName=conn.createStatement();
			Statement getBroadCasterRating= conn.createStatement();
		      //Get the names of the broadcasters
			rsBroadcasterName=getBroadCasterName.executeQuery("select BroadCasterName,broadcasters.BroadCasterID from broadcasters,broadcasternymmap where broadcasternymmap.BroadCasterID=broadcasters.BroadCasterID and NymID='"+strNymID+"' order by "+strCriteria+" desc"); 
			while ( rsBroadcasterName.next() )
			{
				strBroadCasterName=rsBroadcasterName.getString("BroadCasterName");
				vector_Broadcastername.addElement(strBroadCasterName);
				System.out.println("Broad CasterName:"+strBroadCasterName);
				iNumBroadcasters++;
			}	
			System.out.println("Braodcasters"+iNumBroadcasters);
			//The loop runs till maximum no of broadcasters subscribed too or the number of braodcasters actually subscribed to if it is less than the maximum number.
			for( ibroadcasterno=0; ibroadcasterno < MAX_BROADCASTERS && ibroadcasterno < iNumBroadcasters; ibroadcasterno++ )
			{	
				//Get the rating for the url for  that particular broadcaster
				rsBroadcasterInfo=getBroadCasterRating.executeQuery("select Rating,Url from broadcasters,broadcastersrating where broadcastersrating.broadcasterID=broadcasters.broadcasterID and broadcastername='"+vector_Broadcastername.elementAt(ibroadcasterno) +"'");
				System.out.println( "-------------------------------------------------------------" );
				while( rsBroadcasterInfo.next() )
				{
					System.out.println( "\t1" );
					strUrl=rsBroadcasterInfo.getString("Url");
					iRating=rsBroadcasterInfo.getInt("Rating");
					strRating=Integer.toString(iRating);
					System.out.println( "\t2"+ ibroadcasterno);
					//store it in the appropriate hashmap
					switch(ibroadcasterno)
					{
						case 0:hmBroadCaster1.put(strUrl,strRating);break;
						case 1:hmBroadCaster2.put(strUrl,strRating);break;
						case 2:hmBroadCaster3.put(strUrl,strRating);break;
						case 3:hmBroadCaster4.put(strUrl,strRating);break;
						case 4:hmBroadCaster5.put(strUrl,strRating);break;
						default:break;
					}
					System.out.println( "\t3" );
				}
				System.out.println( "\t4" );
			}	
			System.out.println( "\t5" );
				
		}
		catch( Exception e )
		{
			System.out.println ( "120:Database Exception is " + e );
		};  
		
	}
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// end of function GetBroadcasterRating()
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// ReturnBroadcasterRating()
	// Gets the broadcasters rating for a particular url using the url as the parameter.
	// returns a comma and colon seperated string containing the ratings of the broadcaster and the names of the broadcasters.
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	public static String ReturnBroadcasterRating(String strUrl)
	{
		int iRating;
		Vector vector_Rating = new Vector( 20, 5 );
		vector_Rating.clear();
		System.out.println( "url:" + strUrl );
		String strRating;
		//If the nym subscribes to  one or  more broadcasters
		if(iNumBroadcasters >= 1)
		{
			//Obtain the rating for broadcaster1
			String strRating1=( String ) hmBroadCaster1.get( strUrl );
			vector_Rating.addElement(strRating1);
		}
		//If the nym subscribes to two or more broadcasters
		if(iNumBroadcasters >= 2)
		{
			//Obtain the rating for broadcaster2
			String strRating2=( String ) hmBroadCaster2.get( strUrl );
			vector_Rating.addElement(strRating2);
		}
		//If the nym subscribes to 3 or more broadcasters
		if(iNumBroadcasters >= 3)
		{
			//Obtain the rating for broadcaster3
			String strRating3=( String ) hmBroadCaster3.get( strUrl );
			vector_Rating.addElement(strRating3);
		}
		//If the nym subscribes to 4 or more broadcasters
		if(iNumBroadcasters >= 4)
		{
			//Obtain the rating for broadcaster4
			String strRating4=( String ) hmBroadCaster4.get( strUrl );
			vector_Rating.addElement(strRating4);
		}
		//If the nym subscribes to 5 or more broadcasters
		if(iNumBroadcasters == 5)
		{
			//Obtain the rating for broadcaster5
			String strRating5=( String ) hmBroadCaster5.get( strUrl );
			vector_Rating.addElement(strRating5);
		}
		//Convert the vector to string
		strRating=VectorToString(vector_Rating);
		System.out.println("The rating is:"+strRating);
		return(strRating);
	}	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// end of function ReturnBroadcasterRating()
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	
	
	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	//VectorToString()
	// Convert an vector of strings to one string.
	// Put the 'separator' string between each element.
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	public static String VectorToString(Vector vector_Rating) 
	{
		String strseperator1=",";
		String strseperator2=":";
		StringBuffer result = new StringBuffer();
		if (vector_Rating.size() > 0) 
		{
			for (int i=0; i<vector_Rating.size() ; ++i) 
			{
				//Append the name of the broadcaster
				result.append( (String)vector_Broadcastername.elementAt( i ) );
				//Seperate rating and name with a ':'
				result.append(strseperator2);
				//Append the rating of the broadcaster
				result.append(vector_Rating.elementAt(i));
				//Seperate rating and next broadcaster with a ','
				result.append(strseperator1);
			}
		}
		//return the string
		return result.toString();
	}
	
	

	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// calculateRating()
	// Takes in a string and integer - url and current rating
	// Calculates the new rating for the URL depending on
	// old rating and the time.
	// A delay in updation of ratings is implemented in case
	// the site has been taken over by malicious people
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	public static void calculateRating( String strURL, float fCurrRating )
	{
		Date dateCurrTime	= new Date();
		long lCurrTime		= dateCurrTime.getTime();
		
		//get the last time visisted the number of visists and the date of first visit.	
		String	strLastTime		= ( String )hmLastDate.get( strURL );
		String	strNumVisits	= ( String )hmVisits.get( strURL );
		String	strInitTime		= ( String )hmInitDate.get( strURL );

		// Convert strings into long/int
		long	lInitTime		= Long.parseLong( strInitTime );		
		//int	iNumVisits		= 1;
		//Integer.parseInt( strNumVisits );
		long	lLastTime		= Long.parseLong( strLastTime );
		String strModLastdate	= Long.toString( lCurrTime );
		
		if( lCurrTime - lLastTime > THREEHOURSINms ) // if its a new visit
		{
			//System.out.println( "new visit" );
			if( fCurrRating == 0 ) // if rating is zero
			{
				//delay for Phishing calculation for a week to avoid the sites from building reputation quickly				
				if( ( lCurrTime - lInitTime ) > ONEWEEKINms ) // if its beyond the one week time limit
					fCurrRating = 1;
				//System.out.println( "currRating:" + iCurrRating );
			}
			else // increment rating
			{
				fCurrRating = fCurrRating + 1;
				//System.out.println( "currRating:" + iCurrRating );
			}   
			
			// max value of rating
			if( fCurrRating > MAXRATING )
			{
				fCurrRating = MAXRATING;
			}
			System.out.println( "currRating:" + fCurrRating );
			// increment the number of visits
			//iNumVisits++;
			
			//System.out.println("Modified rating"+CurrRating);
			//System.out.println("Modifeied NumVisits"+iNumVisits);
			String strModCurrRating	= Float.toString( fCurrRating );
			//String strModNumVisits	= Integer.toString( iNumVisits );
			
			//Put the updated rating back to the hashmaps 
			hmInternalRating.put(   strURL, strModCurrRating);
			//hmVisits.put(   strURL, strModNumVisits);
			hmLastDate.put( strURL, strModLastdate);
		}
	}
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// end of function calculateRating()
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// decayRating()
	// Takes in two arguments - CurrRating as integer and long date
	// Checks if the URL has not been visited between a year and a week
	// If true, reduces rating by half
	// If false, nothing
	// Repeat for all urls(?)
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	
	public static int decayRating( )
	{
		Date dateObj = new Date();
		long lCurrTime = dateObj.getTime();

		Set	lastDateKeySet = hmLastDate.keySet();
		Iterator iter_lastDateKeySet = lastDateKeySet.iterator();

		while( iter_lastDateKeySet.hasNext() )
		{
			Object keyObj = iter_lastDateKeySet.next();
			String strLastTime = ( String )hmLastDate.get( keyObj );
			long lLastTime = Long.parseLong( strLastTime );

			long lElapsedTime = lCurrTime - lLastTime;
			long lElapsedTimeInDays = lElapsedTime/ONEDAYINms;
			long lCurrTimeInDays = lCurrTime/ONEDAYINms;

						
			if( lElapsedTimeInDays > ONEWEEK && lElapsedTimeInDays < ONEYEAR )
			{
				float fOldRating = Float.parseFloat( ( String )hmInternalRating.get( keyObj ) );
				float fNumerator = (float) fOldRating * lElapsedTimeInDays;
				float fDenominator = (float) 2 * ONEYEAR;
				
				float dNewRating = (float)(fOldRating) - ( fNumerator/fDenominator);
				//((float)(iOldRating/2) *(float) ( lElapsedTimeInDays ) / (float)(  ONEYEAR ));
				
				hmInternalRating.put( keyObj, Double.toString( dNewRating ) );
				
			}
			else if( lElapsedTimeInDays > ONEYEAR )
			{
				// reset hmLastDate to hmm, 8 days or so
				// thats one day more than ONEWEEK
				hmLastDate.put( keyObj, Long.toString(ONEWEEKINms + 10000 ));
				System.out.println("reseting ");
			}
		}
		return 1;
	}
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// end of function decayRating()
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// returnNumBuddies()
	// returns a string 
	// Takes a string as input
	// looks up the number of buddies subscribed to the nym and returns it 
	// returns NULL otherwise
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	public static String returnNumBuddies( String url )
	{
		boolean b=CheckUrl(url);
		String strNumBuddies;
		//Check if the url does not contain numbers
		if(b==false)
		{
			 strNumBuddies= ( String )hmBuddyCount.get( url );
			
		}
		else
		{
			 strNumBuddies=null;
		}
		return strNumBuddies;
	}
	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// returnComments()
	// returns a string
	// Takes a string as input
	// looks up the number of comments for the input url and returns it
	// returns NULL otherwise
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	public static String returnNumComments( String url )
	{
		boolean b=CheckUrl(url);
		String  strNumComments;
		//Check if the url does not contain numbers
		if(b==false)
		{
			 strNumComments = ( String )hmCommentCount.get( url );
			
		}
		else
		{
			 strNumComments=null;
		}
		return strNumComments;
	}
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// returnComments()
	// returns a string
	// Takes a string as input
	// looks up the comments for the input and returns the string
	// returns NULL otherwise
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	public static String returnComments( String url )
	{
		boolean b=CheckUrl(url);
		String strComments;
		//Check if the url does not contain numbers
		if(b==false)
		{
			 strComments = ( String )hmComments.get( url );
			
		}
		else
		{
			 strComments=null;
		}
		return strComments;
	}

		
	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// returnRating()
	// returns a float
	// Takes a string as input
	// looks up the rating for the input and returns the value
	// returns NULL otherwise
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	public static String returnRating( String url )
	{
		
		boolean b=CheckUrl(url);
		StringBuffer  strbufrating=new StringBuffer();
		//Check if the url does not contain numbers
		if(b==false)
		{
		String strExplicitRating= null;
		strExplicitRating = ( String )hmExplicitRating.get( url );
		System.out.println("The string is "+strExplicitRating) ;
		float fExplicitRating=0,fExplicitRating2=0;
		try
		{	
			fExplicitRating =Float.parseFloat( strExplicitRating );
		}
		catch(Exception e)
		{	
			System.out.println("358:The exception is "+e);
		};	
		// check if buddy rating is necessary
		// if it is, the following lines should be removed and explicit rating is used instead of iCurrRating
		if ( fExplicitRating != 0 )
		{
			if( fExplicitRating > 0)			
			{
				strbufrating.append(Float.toString(fExplicitRating));
				strbufrating.append(",");
				strbufrating.append(Float.toString(fExplicitRating2));
			}
			else
			{
				strbufrating.append(Float.toString(fExplicitRating2));
				strbufrating.append(",");
				strbufrating.append(Float.toString(fExplicitRating));
			}
		// return fFinalPositiveRatingOfSite, fFinalNegativeRatingOfSite;
		return strbufrating.toString();
		// iCurrRating = iExplicitRating;
		}
		
		float fFinalNegativeRatingOfSite;
		float fFinalPositiveRatingOfSite;
		
		String	strCurrRating = ( String )hmInternalRating.get( url );
		String	strAvgBuddyRatingPositive = ( String )hmBuddyAvgPositive.get( url );
		String	strAvgBuddyRatingNegative = ( String )hmBuddyAvgNegative.get( url );
		
		float	iCurrRating=0;
		float fAvgBuddyRatingNegative = 0;
		float fAvgBuddyRatingPositive = 0;
		//System.out.println( "Rating:" + rating + "buddy" + buddyavg );
	
		// if strCurrRating is null, its a new website
		if ( strCurrRating == null )
		{
			// if its a new visit, then the prev. rating is 0
			strCurrRating = Float.toString( 0 );
			hmInternalRating.put( url, strCurrRating );
			hmExplicitRating.put( url, strCurrRating );
			
			// its the first visit
			hmVisits.put( url, Float.toString( 1 ) );
			
			Date tmpDate = new Date();
			long lTmpCurrTime = tmpDate.getTime();
			String strTmpCurrTime = Long.toString( lTmpCurrTime );
		
			// store the current time
			hmInitDate.put(url,  strTmpCurrTime  );
			hmLastDate.put(url,  strTmpCurrTime  );
			
			// add to the list of new urls
			VectorOfNewURLs.addElement(url);
			//System.out.println("Url=:"+strNewURL[ iURLCount - 1 ]);
		}
		else // if its not a new visit
		{
			iCurrRating = Float.parseFloat( strCurrRating );

			// call calculateRating() the url
			calculateRating( url, iCurrRating ); 
		}  
		
		if( strAvgBuddyRatingNegative != null )
			fAvgBuddyRatingNegative = Float.parseFloat( strAvgBuddyRatingNegative );
		if( strAvgBuddyRatingPositive != null )
			fAvgBuddyRatingPositive = Float.parseFloat( strAvgBuddyRatingPositive );
		
		if( iCurrRating >= 0 )
		{
			fFinalPositiveRatingOfSite = ( iCurrRating + fAvgBuddyRatingPositive ) / 2;
			fFinalNegativeRatingOfSite = fAvgBuddyRatingNegative;
		}
		else
		{
			fFinalNegativeRatingOfSite = ( iCurrRating + fAvgBuddyRatingNegative ) / 2;
			fFinalPositiveRatingOfSite = fAvgBuddyRatingPositive;
		}
		
		strbufrating.append(Float.toString(fFinalPositiveRatingOfSite));
		strbufrating.append(",");
		strbufrating.append(Float.toString(fFinalNegativeRatingOfSite));
		// return fFinalPositiveRatingOfSite, fFinalNegativeRatingOfSite;
		return strbufrating.toString();
		}
		else
		{
			//the url contains all numbers 
			return null;
		}
	}
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// end of function returnRating()
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// Connect()
	// Connects to the database
	// return value of type Connection
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	public static Connection Connect()
	{
		Connection conn = null;
		
		try
		{
			//Defines the Query statements
			//ResultSet rsBuddy,rsInternal,rsNymID;
			//Connect to the database
			
			String userName = "nettrust";
			String password = "nettrust06162006";
			String url= "jdbc:mysql://localhost/NetTrust";
			Class.forName ("com.mysql.jdbc.Driver").newInstance ();
			conn = DriverManager.getConnection (url, userName, password);
			System.out.println ("Database connection established");
		}
		catch( Exception e )
		{
			// Do nothing
		};  
		return( conn );
	}
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// end of function Connect()
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// CheckUrl()
	// checks for the vaidity of the supplied url
	// If the url contains all numbers the function returns true.
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	

	public static boolean CheckUrl(String url)
	{
		//Pattern p = Pattern.compile("[0-9]*");
        	if(url.matches("[0-9]*"))
		{
			return true;
		}
		else
		{
			return false;
		}

	}
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// end of function CheckUrl()
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	

	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// UpdateDB()
	// dump function basically
	// dumps the contents of the hash map into the database
	// 
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	public static void UpdateDB()
	{
		Connection Conn = Connect();

		int	iCounter;
		
		Statement InsertNewURLs;
		Statement UpdateInternalRating;
		
		try
		{	  
			InsertNewURLs = Conn.createStatement();
			
			for( iCounter = 0; iCounter < VectorOfNewURLs.size(); iCounter++ )
			{
				//System.out.println("Url: "+strNewURL[count1]);
				InsertNewURLs.executeUpdate( "INSERT INTO internalrating VALUES('" + VectorOfNewURLs.elementAt( iCounter ) + "',0,0,0,0,' ','" + strNymID + "','')" );
			
			}
		}
		catch( Exception e )
		{
			System.out.println( e );
		}

		try
		{
			Set keys = hmInternalRating.keySet();         // The set of keys in the map.
			Iterator keyIter = keys.iterator();
			//System.out.println("The map contains the following associations:");
			while ( keyIter.hasNext() )
			{
				Object key = keyIter.next();  // Get the next key.
				String url = key+ " ";
				String strlasttime	= (String)hmLastDate.get(key);
				String initime		= (String)hmInitDate.get(key);
				String ratingi		= (String)hmInternalRating.get(key);
				int rating			= Integer.parseInt(ratingi);
				String  visitsi		= (String)hmVisits.get(key);
				int visits			= Integer.parseInt(visitsi);
				UpdateInternalRating= Conn.createStatement();
				
				try
				{
					UpdateInternalRating.executeUpdate("update internalrating set LastDate='"+strlasttime+"',CurrRating="+rating+",Numvisits="+visits+" ,InitDate="+initime+" where urlName='"+url+"' and Nymid='" + strNymID +"'"); 
				}catch(Exception e)
				{
					System.out.println(e);
				}
			}
		}catch( Exception e )
		{
			System.out.println (e);
		}
	}
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// end of function updateDB()
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */	
	
	public void destroy() {
		System.out.println("NetTrustFinalServlet: destroy()");
	}
}; 


